home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
source
/
vr386
/
joyptrs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-10
|
12KB
|
498 lines
/* Read the joystick, and simulated mouse and key "joysticks" */
// Implemented as pointer drivers. These are good examples of how
// simple pointer drivers can be.
// ALL code in this file by Dave Stampe, 12/24/93
/*
This code is part of the VR-386 project, created by Dave Stampe.
VR-386 is a desendent of REND386, created by Dave Stampe and
Bernie Roehl. Almost all the code has been rewritten by Dave
Stampre for VR-386.
Copyright (c) 1994 by Dave Stampe:
May be freely used to write software for release into the public domain
or for educational use; all commercial endeavours MUST contact Dave Stampe
(dstampe@psych.toronto.edu) for permission to incorporate any part of
this software or source code into their products! Usually there is no
charge for under 50-100 items for low-cost or shareware products, and terms
are reasonable. Any royalties are used for development, so equipment is
often acceptable payment.
ATTRIBUTION: If you use any part of this source code or the libraries
in your projects, you must give attribution to VR-386 and Dave Stampe,
and any other authors in your documentation, source code, and at startup
of your program. Let's keep the freeware ball rolling!
DEVELOPMENT: VR-386 is a effort to develop the process started by
REND386, improving programmer access by rewriting the code and supplying
a standard API. If you write improvements, add new functions rather
than rewriting current functions. This will make it possible to
include you improved code in the next API release. YOU can help advance
VR-386. Comments on the API are welcome.
CONTACT: dstampe@psych.toronto.edu
*/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <bios.h>
#include <conio.h>
#include "pointint.h"
#include "vr_api.h"
#include "vrconst.h" /* for nouse joy ctrl */
#include "pcdevice.h" /* for low-level joystick and keyboard */
#include "intmath.h"
extern int joystick_j1; /* raw joystick results */
extern int joystick_j2; /* modified directly by raw_joystick_read(); */
extern int joystick_j3; /* you may read these elsewhere for trackers */
extern int joystick_j4;
extern int joystick_buttons;
static int joy_ok = 1;
/* This routine reads the joystick, setting x y and buttons */
static int use_pothead = 0; /* used by pot head tracker */
// returns: 0 if OK, 1 if failure, -1 if time to shutoff
static int joyx, joyy, joyb;
static int jcenter_x, jcenter_y;
static int joystick_read()
{
int c, k, jx, jy;
int ovf = 0;
int j;
if(!joy_ok) return -1;
c = 0x03; // determine read mask
if(use_pothead) c |= 0x0C; // force read of second input
for(ovf=0;ovf<30;ovf++) // wait till timeout or success
{
if(!raw_joystick_read(c)) break;
}
if(ovf==30) // not responding! so turn it off
{
joyx = joyy = 0;
joyb = 0;
joy_ok = 0;
return -1;
}
joyb = joystick_buttons;
joyx = joystick_j1-jcenter_x;
joyy = joystick_j2-jcenter_y;
return 0;
}
static int joystick_init()
{
jcenter_x = jcenter_y = 0;
joystick_read();
jcenter_x = joyx;
jcenter_y = joyy;
return joystick_read();
}
/* This routine returns two bits; bit 0 on => joystick 1 found, bit 1 => joystick 2 */
static int joystick_check(void)
{
int c, cc, i, result;
disable();
outportb(0x201,0xff); /* Trigger joystick */
c = inportb(0x201);
c = inportb(0x201);
c = inportb(0x201);
enable();
cc = 0;
for(i=0;i<1000;i++) /* wait a few milliseconds */
cc |= c ^ inportb(0x201); /* and look for changes */
result = 0;
if (cc & 0x03) result |= 1;
if (cc & 0x0C) result |= 2;
return result;
}
pconfig joy_pconfig = {
65536L, 65536L, 65536L, /* position res: mm/tick in <16.16> */
600, 600, 0, -600, -600, 0, /* xyz ranges: */
0, 0, 0, 0, 0, 0, 0, 0, 0, /* no rotation */
640, 480, /* mouse emulation limits (writable) */
P_HASB1 | P_HASB2 | P_HASX | P_HASY, /* databits */
0, 0, 0, /* modes, nullkey, flexnum */
1, 10, 60, /* delay, idelay, reads/sec */
P_IS2DP | P_IS2D, /* uses */
"Joystick Driver for navigation"
};
#define JTHRESHOLD 200
pconfig *joy_driver(int op, POINTER *p, int mode)
{
union REGS r;
int type = FP_OFF(p); /* way to get integer arg. */
switch(op)
{
case DRIVER_CMD:
if (!(type & P_CENTER)) break;
joystick_init();
break;
case DRIVER_INIT:
if(!joystick_check()) return NULL;
joystick_init();
case DRIVER_RESET:
joyx = joyy = joyb = 0;
break;
case DRIVER_READ: /* pointer (2DP) read */
if (mode == P_POINTER)
{
p->x = 0; // first threshold for navigation...
p->y = 0;
if(!joy_ok) break;
joystick_read();
if (abs(joyx)<JTHRESHOLD && abs(joyy)<JTHRESHOLD) goto retbut;
if (joyx>JTHRESHOLD) joyx -= JTHRESHOLD;
else
{
if (joyx<-JTHRESHOLD) joyx += JTHRESHOLD;
else joyx = 0;
}
if (joyy > JTHRESHOLD) joyy -= JTHRESHOLD;
else
{
if (joyy<-JTHRESHOLD) joyy += JTHRESHOLD;
else joyy = 0;
}
p->x = joyx;
p->y = joyy;
retbut:
p->z = 0;
p->buttons = joyb;
}
break;
case DRIVER_CHECK:
if(!joystick_check()) return NULL;
break;
case DRIVER_QUIT:
break;
}
return &joy_pconfig;
}
/************* USE MOUSE TO EMULATE JOYSTICK ***********/
static int oldalt = 0;
static mjx = 0;
static mjy = 0;
static int old_mjx = 0;
static int old_mjy = 0;
#define MJOY_ENABLE 0x1000
#define MJOY_VELOCITY 0x2000
static int mjoyx, mjoyy, mjoyb;
static imouse_joy(int mode)
{
union REGS r;
int x,y,b;
int alt;
if (0==(mode&MJOY_ENABLE))
{
r.h.ah = 2;
int86(0x16, &r, &r);
alt = r.h.al & 8; // look for ALT key (temp mouse on)
if (alt == 0)
{
mjoyx = 0; // no: clear data, exit
mjoyy = 0;
mjoyb = 0;
oldalt = 0;
return 0;
}
else
if (oldalt == 0) // new alt: reset data
{
mjx = 0;
mjy = 0;
oldalt = alt;
}
}
r.x.ax = 3; /* read button status */
int86(0x33, &r, &r);
{
int b=0;
if (r.x.bx & 1) b |= 2;
if (r.x.bx & 2) b |= 1;
mjoyb = b;
}
r.x.ax = 11; /* read motion counters */
int86(0x33, &r, &r);
if(0==(mode&MJOY_VELOCITY))
{
old_mjx = old_mjy = 0;
mjx = ((int) r.x.cx); /* MOUSE STEP */
mjy = ((int) r.x.dx);
}
else
{
if(mjoyb&1) // go back to absolute for rotation
{
mjx = ((int) r.x.cx);
mjy = ((int) r.x.dx);
}
else
{
mjx = mjy = 0;
mjx = old_mjx; /* save for reversion */
mjy = old_mjy;
mjx += ((int) r.x.cx)>>2; /* SPEED STEP */
mjy += ((int) r.x.dx)>>2;
if (mjx < -50) mjx = -50;
if (mjy < -50) mjy = -50;
if (mjx > 50) mjx = 50;
if (mjy > 50) mjy = 50;
old_mjx = mjx;
old_mjy = mjy;
}
}
mjoyx = mjx>>1;
mjoyy = mjy>>1;
return 1;
}
pconfig mjoy_pconfig = {
65536L, 65536L, 65536L, /* position res: mm/tick in <16.16> */
50, 50, 50, -50, -50, -50, /* xyz ranges: */
0, 0, 0, 0, 0, 0, 0, 0, 0, /* no rotation */
640, 480, /* mouse emulation limits (writable) */
P_HASB1 | P_HASB2 | P_HASX | P_HASY, /* databits */
0, 0, 0, /* modes, nullkey, flexnum */
1, 10, 60, /* delay, idelay, reads/sec */
P_IS2DP | P_IS2D, /* uses */
"Mouse used for navigation"
};
static int mjoy_mode = 0;
pconfig *mjoy_driver(int op, POINTER *p, int mode)
{
union REGS r;
int type = FP_OFF(p); /* way to get integer arg. */
switch(op)
{
case DRIVER_CMD:
mjoy_mode = type;
break;
case DRIVER_INIT:
case DRIVER_RESET:
mjoyx = mjoyy = mjoyb = 0;
mjx = mjy = old_mjx = old_mjy = 0;
break;
case DRIVER_READ: /* pointer (2DP) read */
if (mode == P_POINTER)
{
imouse_joy(mjoy_mode);
p->x = mjoyx;
p->y = mjoyy;
p->z = 0;
p->buttons = mjoyb;
}
break;
case DRIVER_CHECK:
break;
case DRIVER_QUIT:
break;
}
return &mjoy_pconfig;
}
/************ USE KEY MONITOR TO FAKE JOYSTICK **********/
// NOTE: IF SHIFT SEEMS STUCK ON, TURN THE NUM LOCK OFF!
extern int use_keyjoy;
#define KJOY_SCALE 15
static int kmjoyx, kmjoyy, kmjoyb;
static int ikey_joy()
{
int x, y, b;
union REGS regs;
x = y = 0;
kmjoyx = x;
kmjoyy = y;
if(!use_keyjoy) return 0;
if(is_key_down(UP_CURSOR_KEYCODE)) y = -KJOY_SCALE;
if(is_key_down(DOWN_CURSOR_KEYCODE)) y = KJOY_SCALE;
if(is_key_down(LEFT_CURSOR_KEYCODE)) x = -KJOY_SCALE;
if(is_key_down(RIGHT_CURSOR_KEYCODE)) x = KJOY_SCALE;
// use BIOS for shift keys: tricky interactions in format
regs.h.ah = 2; // this will always work
int86(0x16, ®s, ®s);
b = (regs.h.al & 3);
kmjoyx = x;
kmjoyy = y;
kmjoyb = b;
if(x || y) return 1;
else return 0;
}
pconfig keymon_pconfig = {
65536L, 65536L, 65536L, /* position res: mm/tick in <16.16> */
50, 50, 50, -50, -50, -50, /* xyz ranges: */
0, 0, 0, 0, 0, 0, 0, 0, 0, /* no rotation */
640, 480, /* mouse emulation limits (writable) */
P_HASB1 | P_HASB2 | P_HASX | P_HASY, /* databits */
0, 0, 0, /* modes, nullkey, flexnum */
1, 10, 60, /* delay, idelay, reads/sec */
P_IS2DP | P_IS2D, /* uses */
"Key monitor for navigation"
};
pconfig *keymon_driver(int op, POINTER *p, int mode)
{
union REGS r;
int type = FP_OFF(p); /* way to get integer arg. */
switch(op)
{
case DRIVER_CMD:
break;
case DRIVER_INIT:
if(!keymon_on) return NULL;
case DRIVER_RESET:
kmjoyx = kmjoyy = kmjoyb = 0;
break;
case DRIVER_READ: /* pointer (2DP) read */
if (mode == P_POINTER)
{
ikey_joy();
p->x = kmjoyx;
p->y = kmjoyy;
p->z = 0;
p->buttons = kmjoyb;
}
break;
case DRIVER_CHECK:
if(!keymon_on) return NULL;
break;
case DRIVER_QUIT:
break;
}
return &keymon_pconfig;
}
/************** KEY PRESSES: COMMANDS FROM KEYBOARD.C ******/
#define KPRESS_SCALE 30
static int kjoyx, kjoyy, kjoyb;
// called from handle_motion_keys() in NAVJOY.C
void key_set_move(int x, int y, int b1, int b2)
{
kjoyb = (b1?1:0) | (b2?2:0);
kjoyx = (!x)?0:((x>0)?KPRESS_SCALE:-KPRESS_SCALE);
kjoyy = (!y)?0:((y>0)?KPRESS_SCALE:-KPRESS_SCALE);
}
pconfig key_pconfig = {
65536L, 65536L, 65536L, /* position res: mm/tick in <16.16> */
50, 50, 50, -50, -50, -50, /* xyz ranges: */
0, 0, 0, 0, 0, 0, 0, 0, 0, /* no rotation */
640, 480, /* mouse emulation limits (writable) */
P_HASB1 | P_HASB2 | P_HASX | P_HASY, /* databits */
0, 0, 0, /* modes, nullkey, flexnum */
1, 10, 60, /* delay, idelay, reads/sec */
P_IS2DP | P_IS2D, /* uses */
"Default Key Press for navigation"
};
pconfig *key_driver(int op, POINTER *p, int mode)
{
union REGS r;
int type = FP_OFF(p); /* way to get integer arg. */
switch(op)
{
case DRIVER_CMD:
break;
case DRIVER_INIT:
case DRIVER_RESET:
kjoyx = kjoyy = kjoyb = 0;
break;
case DRIVER_READ: /* pointer (2DP) read */
if (mode == P_POINTER)
{
p->x = kjoyx;
p->y = kjoyy;
p->z = 0;
p->buttons = kjoyb;
kjoyx = kjoyy = 0;
}
break;
case DRIVER_CHECK:
break;
case DRIVER_QUIT:
break;
}
return &key_pconfig;
}